In [1]:
import csv
data = {}
with open("songdata.csv") as file:
for author,_,_,lyric in csv.reader(file):
data[author] = data.get(author,{})
for word in set(lyric.lower().split()):
data[author][word] = data[author].get(word,0) + 1
In [2]:
data["ABBA"]
Out[2]:
Algo que no hicimos durante la clase, pero que si hay que hacer, es sacar las palabras que no nos dan informacion. Otra cosa que habria que hacer es sacar todos los simbolos.
Si no sabemos hacer algo, siempre podemos recurrir a Stack Overflow
In [3]:
import re
# https://stackoverflow.com/questions/875968/how-to-remove-symbols-from-a-string-with-python
def strip_simbols(string):
return re.sub(r'[^\w]', '', string)
In [4]:
import csv
data = {}
with open("songdata.csv") as file:
for author,_,_,lyric in csv.reader(file):
data[author] = data.get(author,{})
for word in set(lyric.lower().split()):
word = strip_simbols(word)
data[author][word] = data[author].get(word,0) + 1
In [5]:
data["ABBA"]
Out[5]:
In [6]:
for author in data:
print(author)
Importo las utilidades de diccionario de la primer parte del TP, de donde vamos a usar la funcion calcular_distancia
como metrica. Las metricas siempre se definen en base a lo que vayamos a hacer, existen metricas mas o menos aceptadas para ciertas cosas, pero no evita que podamos definir las nuestras propias (con cierto fundamento claro esta).
In [7]:
import utilidades_diccionarios
Pruebo que tanto se parecen algunos artistas al azar. Voy a necesitar markdown para que se vea mas lindo, asi que puedo importar la funcion para mostrarlo directamente desde el output:
In [8]:
from IPython.display import display, Markdown, Latex
In [9]:
import random
artists = list(data.keys())
In [10]:
artist_a = random.choice(artists)
artist_b = random.choice(artists)
diference = utilidades_diccionarios.calcular_distancia(data[artist_a],data[artist_b],2)
display(Markdown( f'Diferencia entre *{artist_a}* y _{artist_b}_ es: **{diference}** '))
In [11]:
artist_a = random.choice(artists)
artist_b = random.choice(artists)
diference = utilidades_diccionarios.calcular_distancia(data[artist_a],data[artist_b],2)
display(Markdown( f'Diferencia entre *{artist_a}* y _{artist_b}_ es: **{diference}** '))
In [12]:
artist_a = random.choice(artists)
artist_b = random.choice(artists)
diference = utilidades_diccionarios.calcular_distancia(data[artist_a],data[artist_b],2)
display(Markdown( f'Diferencia entre *{artist_a}* y _{artist_b}_ es: **{diference}** '))
In [13]:
artist_a = random.choice(artists)
artist_b = random.choice(artists)
diference = utilidades_diccionarios.calcular_distancia(data[artist_a],data[artist_b],2)
display(Markdown( f'Diferencia entre *{artist_a}* y _{artist_b}_ es: **{diference}** '))
In [14]:
artist_a = random.choice(artists)
artist_b = random.choice(artists)
diference = utilidades_diccionarios.calcular_distancia(data[artist_a],data[artist_b],2)
display(Markdown( f'Diferencia entre *{artist_a}* y _{artist_b}_ es: **{diference}** '))
In [15]:
import csv
data = {}
authors = ["ABBA"]
with open("songdata.csv") as file:
for author,_,_,lyric in csv.reader(file):
if author not in authors:
continue
prev = ""
for word in lyric.lower().split():
new_word = word
while new_word and not new_word[-1].isalpha():
new_word = new_word[:-1]
data[prev] = data.get(prev,[])
data[prev].append(new_word)
prev = new_word
if not word[-1].isalpha():
data[prev] = data.get(prev,[])
data[prev].append(word[-1])
prev = word[-1]
data[prev] = data.get(prev,[])
data[prev].append("")
Lo que hice es armar un diccionario con las palabras de las canciones, y a cada una asociarle una lista con todas las palabras que aparecen despues de esa. Al ser una lista con repeticiones, si elijo una palabra al azar, es mas probable que elija una palabra que aparece mas seguido que otras. Entonces, al igual que con el predictivo, puedo armar una cancion de ABBA asi:
In [16]:
cancion = []
prev = ""
for _ in range(100):
next_word = random.choice(data[prev])
cancion.append(next_word)
prev = next_word
display(Markdown("_" + " ".join(cancion) + "_") )
Incluso para ser algo rapido, alguna clase de sentido tiene. Si le queremos dar mas sentido, deberiamos analizar mas que la palabra anterior, por ejemplo las 2 anteriores, y eso deberia mejorar
In [17]:
import csv
data = {}
authors = ["ABBA"]
with open("songdata.csv") as file:
prev = ("","")
for author,_,_,lyric in csv.reader(file):
if author not in authors:
continue
for word in lyric.lower().split():
new_word = word
if not word[0].isalpha():
data[prev] = data.get(prev,[])
data[prev].append(word[0])
prev = (prev[-1],word[0])
while new_word and not new_word[0].isalpha():
new_word = new_word[1:]
while new_word and not new_word[-1].isalpha():
new_word = new_word[:-1]
data[prev] = data.get(prev,[])
data[prev].append(new_word)
prev = (prev[-1],new_word)
if not word[-1].isalpha():
data[prev] = data.get(prev,[])
data[prev].append(word[-1])
prev = (prev[-1],word[-1])
data[prev] = data.get(prev,[])
data[prev].append("")
prev = (prev[-1],"")
In [18]:
cancion = []
prev = ("","")
for _ in range(100):
next_word = random.choice(data[prev])
cancion.append(next_word)
prev = (prev[-1],next_word)
display(Markdown("_" + " ".join(cancion) + "_") )
Tambien podemos combinar varias canciones de varios artistas para hacer algo aun mas loco.
In [19]:
import csv
data = {}
authors = ["ABBA","Stevie Wonder","Hank Williams"]
with open("songdata.csv") as file:
prev = ("","")
for author,_,_,lyric in csv.reader(file):
if author not in authors:
continue
for word in lyric.lower().split():
new_word = word
if not word[0].isalpha():
data[prev] = data.get(prev,[])
data[prev].append(word[0])
prev = (prev[-1],word[0])
while new_word and not new_word[0].isalpha():
new_word = new_word[1:]
while new_word and not new_word[-1].isalpha():
new_word = new_word[:-1]
data[prev] = data.get(prev,[])
data[prev].append(new_word)
prev = (prev[-1],new_word)
if not word[-1].isalpha():
data[prev] = data.get(prev,[])
data[prev].append(word[-1])
prev = (prev[-1],word[-1])
data[prev] = data.get(prev,[])
data[prev].append("")
prev = (prev[-1],"")
In [20]:
cancion = []
prev = ("","")
for _ in range(100):
next_word = random.choice(data[prev])
cancion.append(next_word)
prev = (prev[-1],next_word)
display(Markdown("_" + " ".join(cancion) + "_") )
La magia aca, es que mientras menor sea la distancia entre 2 autores mejor se van a combinar las diferentes letras